
#include "CanTp.h"

/******************************************************************************
*    Local Function
******************************************************************************/
/*
 * RxChannel: FC
 * */
static void CanTp_Local_RxCh_TxConfirmation(uint8 ChId_u8, PduIdType TxPduId_u16, Std_ReturnType result)
{
    CanTp_RxChannelType *l_RxCh_pst;
    const CanTp_RxSduCfg_Type *l_RxSduCfg_cpst;

    l_RxCh_pst = &CanTp_RxChControlBlock[ChId_u8];
    l_RxSduCfg_cpst = CanTp_CfgPtr->RxSdu_cpst + l_RxCh_pst->ActiveSduId_u8;

    if(result == E_OK)
    {
		switch(l_RxCh_pst->FS_u8)
		{
			case CANTP_FC_CTS:
				CANTP_TIMEROUT_SET(l_RxCh_pst->StateTimeoutCnt_u16, l_RxSduCfg_cpst->TimeOut_cst.NcTicks_u16);   /* N_Cr */
				CanTp_RxChState_au8[ChId_u8] = CANTP_RXCH_WAIT_CF;
				break;

			case CANTP_FC_WAIT:
				CANTP_TIMEROUT_SET(l_RxCh_pst->StateTimeoutCnt_u16, l_RxSduCfg_cpst->TimeOut_cst.NbTicks_u16);   /* N_Br */
				CanTp_RxChState_au8[ChId_u8] = (l_RxCh_pst->RemainingSduLength > 0u) ? CANTP_RXCH_TRANSMIT_FC : CANTP_CH_IDLE;
				break;

			case CANTP_FC_OVERFLOW:
				PduR_CanTpRxIndication(l_RxSduCfg_cpst->PduRPduHandleId_u16, E_NOT_OK);
				CanTp_RxChState_au8[ChId_u8] = CANTP_CH_IDLE;
				break;

			default:
				break;
		}
    }
    else
    {
    	PduR_CanTpTxConfirmation(l_RxSduCfg_cpst->PduRPduHandleId_u16, E_NOT_OK);	/* TRACE[SWS_CanTp_00355] */
		CanTp_RxChState_au8[ChId_u8] = CANTP_CH_IDLE;
    }

    CANTP_UNLOCK_TXPDU(TxPduId_u16);    /* SWS_CanTp_00248 */
}

/*
 * TxChannel: SF, FF, CF
 * */
static void CanTp_Local_TxCh_TxConfirmation(uint8 ChId_u8, PduIdType TxPduId_u16, Std_ReturnType result)
{
    CanTp_TxChannelType *l_TxCh_pst;
    const CanTp_TxSduCfg_Type *l_TxSduCfg_cpst;
    uint8 l_MaxCopyLength_u8;

    l_TxCh_pst = &CanTp_TxChControlBlock[ChId_u8];
    l_TxSduCfg_cpst = CanTp_CfgPtr->TxSdu_cpst + l_TxCh_pst->ActiveSduId_u8;

    if(result == E_OK)
    {
		/******************************************************************************
		*    Reload STminTickCnt_u16 timeout
		******************************************************************************/
		l_MaxCopyLength_u8 = l_TxSduCfg_cpst->TX_DL_u8 - CANTP_GET_DATA_FIELD_OFFSET(l_TxSduCfg_cpst->AddrInfo_cst.AddressFormat_u8, l_TxCh_pst->NPCI_Type);
		l_TxCh_pst->RemainingSduLength = (l_TxCh_pst->RemainingSduLength < l_MaxCopyLength_u8) ? 0u : (l_TxCh_pst->RemainingSduLength - l_MaxCopyLength_u8);

		if(l_TxCh_pst->NPCI_Type == CANTP_NPCI_TYPE_CF)
		{
			l_TxCh_pst->SN_u8 = (l_TxCh_pst->SN_u8 + 1) & 0xF;
			l_TxCh_pst->RemainingBlockCfsNum_u8 = (l_TxCh_pst->RemainingBlockCfsNum_u8 > 0) ? (l_TxCh_pst->RemainingBlockCfsNum_u8 - 1): 0;
			CANTP_TIMEROUT_SET(l_TxCh_pst->SeparationTimeCnt_u16, l_TxCh_pst->STminTickCnt_u16);
		}

		/******************************************************************************
		*    SF,FF,CF process
		******************************************************************************/
		if(l_TxCh_pst->RemainingSduLength == 0u)
		{   /* SF end, or last CF end */
			CanTp_TxChState_au8[ChId_u8] = CANTP_CH_IDLE;
			PduR_CanTpTxConfirmation(l_TxSduCfg_cpst->PduRPduHandleId_u16, E_OK);	/* TRACE[SWS_CanTp_00090][SWS_CanTp_00204] */
		}
		else if(l_TxCh_pst->RemainingBlockCfsNum_u8 != 0u)
		{   /* Not last CF in Block */
			CANTP_TIMEROUT_SET(l_TxCh_pst->StateTimeoutCnt_u16, l_TxSduCfg_cpst->TimeOut_cst.NcTicks_u16);   /* N_Cs */
			CanTp_TxChState_au8[ChId_u8] = CANTP_TXCH_TRANSMIT_CF;
			l_TxCh_pst->NPCI_Type = CANTP_NPCI_TYPE_CF;
		}
		else
		{   /* FF end or block CF end */
			/* TRACE[SWS_CanTp_00315] */
			CANTP_TIMEROUT_SET(l_TxCh_pst->StateTimeoutCnt_u16, l_TxSduCfg_cpst->TimeOut_cst.NbTicks_u16);   /* N_Bs */
			CanTp_TxChState_au8[ChId_u8] = CANTP_TXCH_WAIT_FC;
			l_TxCh_pst->NPCI_Type = CANTP_NPCI_TYPE_FC;
		}
    }
    else
    {
		CanTp_TxChState_au8[ChId_u8] = CANTP_CH_IDLE;
    	PduR_CanTpTxConfirmation(l_TxSduCfg_cpst->PduRPduHandleId_u16, E_NOT_OK);	/* TRACE[SWS_CanTp_00355] */
    }

    CANTP_UNLOCK_TXPDU(TxPduId_u16);    /* TRACE[SWS_CanTp_00248] */
}

/* TRACE[SWS_CanTp_00076][SWS_CanTp_00215] */
void CanTp_TxConfirmation(PduIdType TxPduId_u16, Std_ReturnType result)
{
    uint8 l_ChId_u8;

    /* Step : Get ChannelId_u8 by TxPduId */
    l_ChId_u8 = CANTP_GET_CH_ID_FROM_TXPDU(TxPduId_u16);

    /* Step : Set next channel status  */
    if(CanTp_RxChState_au8[l_ChId_u8] == CANTP_RXCH_WAIT_TRANSMIT_CONFORMATION)
    {   /* RxChannel: FC */
        CanTp_Local_RxCh_TxConfirmation(l_ChId_u8, TxPduId_u16, result);
    }
    else if(CanTp_TxChState_au8[l_ChId_u8] == CANTP_TXCH_WAIT_TRANSMIT_CONFORMATION)
    {   /* TxChannel: SF, FF, CF */
        CanTp_Local_TxCh_TxConfirmation(l_ChId_u8, TxPduId_u16, result);
    }
    else
    {
        /* Ignore */
    }
}
